import requests
import threading
import time
import json
import datetime


class StatusSender(threading.Thread):
    def __init__(self, logger, ip, port, configData, jobList):
        threading.Thread.__init__(self)
        self._logger = logger
        self._startTime = datetime.datetime.now()
        self._configData = configData
        self._isRunning = True
        self._isOnline = True
        self._currentJob = Nonec
        self._startCurrentJob = None
        self._jobList = jobList
        self._ip = ip
        self._port = port
        self._headerLogInfo = "[" + "STATUS SENDER".rjust(19) + "]\t"
        self._lastCommunicationTime = None
        self.start()

    def sendInitStatus(self):
        uptime = (datetime.datetime.now() - self._startTime).total_seconds()
        uptimeCurrentJob = self.getUptimeCurrentJob()
        self._logger.info(self._headerLogInfo + "Sending initial message")
        self.sendStatus("enabled", 'Init Message', uptime, self._currentJob, uptimeCurrentJob, self._jobList)

    def run(self):
        self._logger.info(self._headerLogInfo + "Status sender started")
        self.sendInitStatus()
        while(self._isRunning):
            time.sleep(15)
            uptime = (datetime.datetime.now() - self._startTime).total_seconds()
            uptimeCurrentJob = self.getUptimeCurrentJob()
            self._logger.info(self._headerLogInfo + "Sending polling message")
            self.sendStatus("enabled", 'Polling Message', uptime, self._currentJob, uptimeCurrentJob, self._jobList)

    def getData(self, status, message, uptime, currentJob, uptimeCurrentJob, jobList):
        lastCommunicationTime = None
        if self._lastCommunicationTime is not None:
            lastCommunicationTime = self._lastCommunicationTime.strftime('%Y-%m-%d %H:%M:%S')
        data = {
            'payload': json.dumps({
                self._ip: {
                    "status": status,
                    "message": message,
                    "uptime": uptime,
                    "current_job": currentJob,
                    "uptime_current_job": uptimeCurrentJob,
                    "queue": jobList,
                    "last_communication_time": lastCommunicationTime
                },
            }),
            'token': 'JOB4CI_AGENT'
        }
        return data

    def sendStatus(self, status, message, uptime, currentJob, uptimeCurrentJob, jobList):
        self._logger.debug(self._headerLogInfo + "Preparing data for status message")
        data = self.getData(status, message, uptime, currentJob, uptimeCurrentJob, jobList)
        self._logger.info(self._headerLogInfo + "Status message data prepared: ".format(data))
        try:
            res = requests.post(self._configData['ciAgentStatusJob'], data=data, timeout=0.2)
            self._lastCommunicationTime = datetime.datetime.now()
            self._logger.info(self._headerLogInfo + "Message sent, response content: {}".format(res.content))
        except Exception as e:
            self._logger.exception(self._headerLogInfo + "Exception while sending message to Jenkins: {}"
                                   .format(str(e)))

    def goOffline(self):
        self._isOnline = False
        uptime = (datetime.datetime.now() - self._startTime).total_seconds()
        uptimeCurrentJob = self.getUptimeCurrentJob()
        self.sendStatus('disabled', 'CI_Agent has been disabled', uptime, self._currentJob, uptimeCurrentJob,
                        self._jobList)

    def goOnline(self):
        self._isOnline = True
        uptime = (datetime.datetime.now() - self._startTime).total_seconds()
        uptimeCurrentJob = self.getUptimeCurrentJob()
        self.sendStatus('eanbled', 'CI_Agent has been enabled', uptime, self._currentJob, uptimeCurrentJob,
                        self._jobList)

    def setCurrentJob(self, job):
        self._currentJob = job
        if job is not None:
            self._startCurrentJob = datetime.datetime.now()
        else:
            self._startCurrentJob = None

    def setJobList(self, jobList):
        self._jobList = jobList

    def sendClosingStatus(self):
        uptime = (datetime.datetime.now() - self._startTime).total_seconds()
        uptimeCurrentJob = self.getUptimeCurrentJob()
        self.sendStatus('offline', 'CI_Agent has been closed', uptime, self._currentJob, uptimeCurrentJob,
                        self._jobList)

    def getUptimeCurrentJob(self):
        uptimeCurrentJob = 0
        if self._startCurrentJob is not None:
            uptimeCurrentJob = (datetime.datetime.now() - self._startCurrentJob).total_seconds()
        return uptimeCurrentJob

    def destroy(self):
        self._sendClosingStatus()
        self._isRunning = False
